package com.bizmda.bizsip.converter;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import com.bizmda.bizsip.common.BizException;
import com.bizmda.bizsip.common.BizResultEnum;
import com.bizmda.bizsip.config.AbstractSinkConfig;
import com.bizmda.bizsip.config.CommonSourceConfig;
import com.bizmda.bizsip.config.SinkConfigMapping;
import com.bizmda.bizsip.config.SourceConfigMapping;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;

/**
 * 格式转换器处理类
 */
@Slf4j
public class Converter {
    private AbstractConverter converter;
//    private List<PredicateRuleConfig> serviceRules = null;

    /**
     * 根据source-id获取格式转换器调用接口
     * @param sourceId 指定Source层模块的source-id
     * @return 格式转换器调用接口
     */
    public static Converter getSourceConverter(String sourceId) {
        Converter converter = new Converter();
        SourceConfigMapping sourceConfigMapping = SpringUtil.getBean(SourceConfigMapping.class);
        CommonSourceConfig sourceConfig = sourceConfigMapping.getSourceId(sourceId);
        try {
            if (sourceConfig == null) {
                throw new BizException(BizResultEnum.SOURCE_ID_NOTFOUND, "source:" + sourceId);
            }
            String converterType = (String) sourceConfig.getConverterMap().get("type");
            Class<? extends AbstractConverter> clazz = (Class<? extends AbstractConverter>) AbstractConverter.CONVERTER_TYPE_MAP.get(converterType);
            if (clazz == null) {
                throw new BizException(BizResultEnum.CONVERTOR_NOT_SET);
            }

            try {
                converter.converter = clazz.getDeclaredConstructor().newInstance();
            } catch (InstantiationException | IllegalAccessException
                    | InvocationTargetException | NoSuchMethodException e) {
                throw new BizException(BizResultEnum.CONVERTOR_CREATE_ERROR, e);
            }
            converter.converter.init(sourceConfigMapping.getConfigPath(), sourceConfig.getConverterMap());
        } catch (BizException e) {
            log.error("getSourceConverter("+sourceId+")出错!",e);
            return null;
        }
        return converter;
    }

    /**
     * 根据sink-id获取格式转换器调用接口
     * @param sinkId Sink层模块的sink-id
     * @return 格式转换器调用接口
     */
    public static Converter getSinkConverter(String sinkId) {
        Converter converter = new Converter();
        SinkConfigMapping sinkConfigMapping = SpringUtil.getBean(SinkConfigMapping.class);
        AbstractSinkConfig sinkConfig = sinkConfigMapping.getSinkConfig(sinkId);
        try {
            if (sinkConfig == null) {
                throw new BizException(BizResultEnum.SINK_NOT_SET, "sinkId[" + sinkId + "]在sink.yml中没有配置");
            }
            if (sinkConfig.getConverterMap() == null) {
                converter.converter = null;
                return converter;
            }
            String converterType = (String) sinkConfig.getConverterMap().get("type");
            Class<Object> clazz = (Class<Object>) AbstractConverter.CONVERTER_TYPE_MAP.get(converterType);
            if (clazz == null) {
                throw new BizException(BizResultEnum.CONVERTOR_NOT_SET);
            }
            try {
                converter.converter = (AbstractConverter) clazz.getDeclaredConstructor().newInstance();
            } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                throw new BizException(BizResultEnum.CONVERTOR_CREATE_ERROR, e);
            }
            converter.converter.init(sinkConfigMapping.getConfigPath(), sinkConfig.getConverterMap());
        }
        catch (BizException e) {
            log.error("getSinkConverter("+sinkId+")出错!",e);
            return null;
        }
        return converter;
    }

    /**
     * 获取底层格式转换器
     * @return 底层格式转换器对象
     */
    public AbstractConverter getConverter() {
        return this.converter;
    }

    /**
     * 消息报文的解包
     * @param inMessage 待解包的消息报文
     * @return 解包完成后的消息报文
     * @throws BizException Biz-SIP应用异常
     */
    public JSONObject unpack(byte[] inMessage) throws BizException {
        return this.converter.unpack(inMessage);
    }

    /**
     * 消息报文的打包
     * @param inMessage 待打包的消息报文
     * @return 打包完成后的消息报文
     * @throws BizException Biz-SIP应用异常
     */
    public byte[] pack(JSONObject inMessage) throws BizException {
        return this.converter.pack(inMessage);
    }

}
